#include "ShaderRegistry.h"
#include "Shader.h"
#include <map>

using namespace GxLibBasic;

namespace RayTracePro
{
	typedef int (*GetShaderCountFunc)();
	typedef void (*GetShaderCtorFunc)(int id, char ** name, CreateShaderFunc * func);

	class ShaderRegistryImpl : public ShaderRegistry
	{
	private:
		std::map<String, CreateShaderFunc> registry;
	public:
		virtual void RegisterShader(const wchar_t * name, CreateShaderFunc shader_ctor)
		{
			registry[name] = shader_ctor;
		}
		virtual int LoadShaderLibrary(const wchar_t * libraryName)
		{
			HMODULE lib = LoadLibraryW(libraryName);
			if (lib)
			{
				GetShaderCountFunc countFunc = (GetShaderCountFunc)GetProcAddress(lib, "GetShaderCount");
				GetShaderCtorFunc getFunc = (GetShaderCtorFunc)GetProcAddress(lib, "GetShaderCtor");
				if (!countFunc) return 0;
				if (!getFunc) return 0;
				int count = countFunc();
				for (int i = 0; i < count; i++)
				{
					char * name;
					CreateShaderFunc ctor;
					getFunc(i, &name, &ctor);
					registry[name] = ctor;
				}
				return count;
			}
			return 0;
		}
		virtual CreateShaderFunc FindShaderConstructor(const wchar_t * name)
		{
			std::map<String, CreateShaderFunc>::iterator iter = registry.find(name);
			if (iter != registry.end())
			{
				return iter->second;
			}
			return 0;
		}
		virtual ShadingNode * CreateShader(const wchar_t * name)
		{
			CreateShaderFunc ctor = FindShaderConstructor(name);
			if (ctor)
				return ctor();
			else
				return 0;
		}
	};

	ShaderRegistry * CreateShaderRegistry()
	{
		return new ShaderRegistryImpl();
	}
}